#include "tfrmstruct.h"
#include "ui_tfrmstruct.h"
#include "tlr.h"
#include "tmonitortreedelegate.h"
#include "tlrsyntaxhighlighter.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QStyleFactory>
#include <QHeaderView>
#include <QToolTip>
#include <QSplitter>

TFrmStruct::TFrmStruct(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TFrmStruct)
{
    //UI初始化
    {
        ui->setupUi(this);

        m_treeStructMonitor->setItemDelegate(new TMonitorTreeDelegate(this));
        //设置文本框
        m_teStructFormat = new QTextEdit(this);
        QFont nfont;
        nfont.setFamily("Courier");
        nfont.setFixedPitch(true);
        nfont.setPointSize(10);
        m_teStructFormat->setFont(nfont);
        m_teStructFormat->setReadOnly(true);
        TLRSyntaxHighlighter *psyntaxhighlighter = new TLRSyntaxHighlighter(m_teStructFormat->document());
        psyntaxhighlighter->setSyntaxFormat(TSyntaxFormat::syntaxFmtCpp);
        //组合查看器
        QList<int> nsizes;
        nsizes.append(160);
        nsizes.append(200);
        QSplitter *pmonitordragableboundary = new QSplitter(this);
        pmonitordragableboundary->addWidget(m_teStructFormat);
        pmonitordragableboundary->addWidget(m_treeStructMonitor);
        pmonitordragableboundary->setStretchFactor(0,0);
        pmonitordragableboundary->setStretchFactor(1,1);
        pmonitordragableboundary->setSizes(nsizes);
        pmonitordragableboundary->setContentsMargins(0,0,0,0);
        //组合主面板
        QVBoxLayout *pvblcontent = new QVBoxLayout;
        pvblcontent->addWidget(pmonitordragableboundary);
        setLayout(pvblcontent);
        //结构体解析树属性
        QStringList nheaderlabels = {"名称","值"};
        m_treeStructMonitor->setHeaderLabels(nheaderlabels);
        m_treeStructMonitor->setColumnWidth(0,160);
        QHeaderView *ptreeheader = m_treeStructMonitor->header();
        ptreeheader->setSectionResizeMode(0,QHeaderView::Fixed);
        m_treeStructMonitor->setAlternatingRowColors(true);
    }
    //信号槽
    {
        //结构体数据更新
        connect(TLR::get(),&TLR::sigStructDataUpdate,this,&TFrmStruct::slotStructDataUpdate);
        //树条目内容变化
        connect(m_treeStructMonitor,&QTreeWidget::itemChanged,this,&TFrmStruct::slotTreeWidgetItemChanged);
    }
}

TFrmStruct::~TFrmStruct()
{
    delete ui;
}

/*
 * 重置
 * nindex : 结构体序号
 */
void TFrmStruct::reset(int nindex)
{
    m_index = nindex;
    dataToUI(TUIType::uiFrame);
}

/*
 * 读取数据
 * nequidstr   : 设备识别字
 * nparastaadd : 设备起始地址
 * nip         : IP地址
 * nport       : 端口
 */
void TFrmStruct::rdPara(const QString &nequidstr,int nparastaadd,const QHostAddress &nip,int nport)
{
    TLRStruct nlrstruct = TLR::get()->m_lrStructModel.getStruct(m_index);
    TLR::get()->m_lrStructModel.setCommIndex(m_index);
    auto nsndbytes = TLR::rdPara(nequidstr,nparastaadd,nlrstruct.getSize());
    TLR::get()->udpSockAnyWrite(nsndbytes,nip,nport);
}

/*
 * 读取串口数据
 * nequidstr : 设备识别字
 * nparastaadd : 数据起始地址
 * nserialaddr : 串口地址
 */
void TFrmStruct::rdParaSerial(const QString &nequidstr, int nparastaadd, int nserialaddr)
{
    TLRStruct nlrstruct = TLR::get()->m_lrStructModel.getStruct(m_index);
    TLR::get()->m_lrStructModel.setCommIndex(m_index);
    auto nsndbytes = TLR::rdParaSerial(nequidstr,nparastaadd,nlrstruct.getSize(),quint16(nserialaddr));
    TLR::get()->serialPortWrite(nsndbytes.front(),nlrstruct.getSize());
}

/*
 * 下发数据
 * nequidstr   : 设备识别字
 * nparastaadd : 设备起始地址
 * nip         : IP地址
 * nport       : 端口
 */
void TFrmStruct::wrPara(const QString &nequidstr, int nparastaadd, const QHostAddress &nip, int nport)
{
    //刷新
    TLRStruct nlrstruct = TLR::get()->m_lrStructModel.getStruct(m_index);
    encodeTreeToStruct(nlrstruct);
    //下发
    TLR::get()->m_lrStructModel.setCommIndex(m_index);
    auto nsndbytes = TLR::wrPara(nequidstr,nparastaadd,nlrstruct.getSize(),nlrstruct.memData.constData());
    switch (TLR::get()->m_lrStructModel.getCommType()) {
    case TCommType::ctNet: {
        TLR::get()->udpSockAnyWrite(nsndbytes,nip,nport);
        break;
    }
    case TCommType::ctSerial: {
        QList<int> readSizeList;
        for(int i=0;i<nsndbytes.size();i++) {
            //串口下发不需要等待太多数据回复
            readSizeList.append(90);
        }
        TLR::get()->serialPortWrite(nsndbytes,readSizeList);
        break;
    }
    }
}

/*
 * 控制数据
 * nequidstr   : 设备识别字
 * nparastaadd : 设备起始地址
 * nip         : IP地址
 * nport       : 端口
 */
void TFrmStruct::ctlPara(const QString &nequidstr, int nparastaadd, const QHostAddress &nip, int nport)
{
    //刷新
    TLRStruct nlrstruct = TLR::get()->m_lrStructModel.getStruct(m_index);
    encodeTreeToStruct(nlrstruct);
    //下发
    TLR::get()->m_lrStructModel.setCommIndex(m_index);
    auto nsndbytes = TLR::ctlPara(nequidstr,nparastaadd,nlrstruct.getSize(),nlrstruct.memData.constData());
    switch (TLR::get()->m_lrStructModel.getCommType()) {
    case TCommType::ctNet: {
        TLR::get()->udpSockAnyWrite(nsndbytes,nip,nport);
        break;
    }
    case TCommType::ctSerial: {
        break;
    }
    }
}

/*
 * UI操作
 * nuitype : UI操作类型
 */
void TFrmStruct::dataToUI(const TUIType &nuitype)
{
    switch (nuitype) {
    case TUIType::uiFrame: {
        auto &nlrstructmodel = TLR::get()->m_lrStructModel;
        TLRStruct nlrstruct = nlrstructmodel.getStruct(m_index);
        //结构体原始格式
        m_teStructFormat->setPlainText(nlrstruct.toCppString());
        //结构体分析
        m_treeStructMonitor->clear();
        decodeStructToTree(0,nlrstruct,nlrstruct.memData);
        //模式
        if(nlrstructmodel.getMode() == "debug") {
            m_teStructFormat->setVisible(true);
        }
        else {
            m_teStructFormat->setVisible(false);
        }
        break;
    }
    }
}

/*
 * 结构体解析到树
 * npreoffset  : 偏移
 * nlrstruct   : 待解析的结构体
 * nactmemdata : 实际的内存数据
 * prootitem   : 上一级节点
 */
void TFrmStruct::decodeStructToTree(int npreoffset,const TLRStruct &nlrstruct,const QByteArray nactmemdata,QTreeWidgetItem *prootitem)
{
    for(int istructmember=0;istructmember<nlrstruct.member.size();istructmember++) {
        const TLRStructMember &nlrstructmember = nlrstruct.member.at(istructmember);
        QTreeWidgetItem *ptopitem = new QTreeWidgetItem;
        //是否可编辑
        if(nlrstructmember.isEditable()) {
            Qt::ItemFlags ntopitemflags = ptopitem->flags();
            ptopitem->setFlags(ntopitemflags | Qt::ItemIsEditable);
        }
        //名称
        ptopitem->setText(0,nlrstructmember.name);
        //值
        ptopitem->setText(1,nlrstructmember.getValStr(nactmemdata,npreoffset));
        ptopitem->setTextColor(1,nlrstructmember.getValColor());
        //偏移
        ptopitem->setText(2,nlrstructmember.getOffsetStr(npreoffset));
        //数据类型
        ptopitem->setText(3,nlrstructmember.getFullType());
        //处理数组类型
        if(nlrstructmember.isArray()) {
            for(int iarr=0;iarr<nlrstructmember.count;iarr++) {
                QTreeWidgetItem *psubitem = new QTreeWidgetItem;
                if(nlrstructmember.isEditable(iarr)) {
                    Qt::ItemFlags nsubitemflags = psubitem->flags();
                    psubitem->setFlags(nsubitemflags | Qt::ItemIsEditable);
                }
                //名称
                psubitem->setText(0,QString("[%1]").arg(iarr));
                //值
                psubitem->setText(1,nlrstructmember.getValStr(nactmemdata,npreoffset,iarr));
                psubitem->setTextColor(1,nlrstructmember.getValColor(iarr));
                //偏移
                psubitem->setText(2,nlrstructmember.getOffsetStr(npreoffset,iarr));
                //数据类型
                psubitem->setText(3,nlrstructmember.type);
                //处理自定义数据类型
                if(!nlrstructmember.isPlainDataType()) {
                    TLRStruct nlrstructtodecode = TLR::get()->m_lrStructModel.getStruct(nlrstructmember.type);
                    decodeStructToTree(nlrstructmember.getOffset(npreoffset,iarr),nlrstructtodecode,nactmemdata,psubitem);
                }
                ptopitem->addChild(psubitem);
            }
        }
        //非数组类型
        else {
            //处理自定义数据类型
            if(!nlrstructmember.isPlainDataType()) {
                TLRStruct nlrstructtodecode = TLR::get()->m_lrStructModel.getStruct(nlrstructmember.type);
                decodeStructToTree(nlrstructmember.getOffset(npreoffset),nlrstructtodecode,nactmemdata,ptopitem);
            }
        }
        if(prootitem) {
            prootitem->addChild(ptopitem);
        }
        else {
            m_treeStructMonitor->addTopLevelItem(ptopitem);
        }
    }
}

/*
 * 树恢复到结构体
 * nlrstruct : 结构体数据
 */
void TFrmStruct::encodeTreeToStruct(TLRStruct &nlrstruct)
{
    for(int itopitem=0;itopitem<m_treeStructMonitor->topLevelItemCount();itopitem++) {
        QTreeWidgetItem *ptopitem = m_treeStructMonitor->topLevelItem(itopitem);
        if(ptopitem) {
            queryTreeItemToStruct(ptopitem,nlrstruct);
        }
    }
}

/*
 * 遍历树条目到结构体
 * ptreeitem : 树条目
 * nlrstruct : 结构体数据
 */
void TFrmStruct::queryTreeItemToStruct(const QTreeWidgetItem *ptreeitem,TLRStruct &nlrstruct)
{
    if(ptreeitem) {
        if(ptreeitem->childCount() == 0) {
            nlrstruct.setPara(ptreeitem->text(2),ptreeitem->text(3),ptreeitem->text(1));
        }
        else {
            for(int i=0;i<ptreeitem->childCount();i++) {
                QTreeWidgetItem *psubtreeitem = ptreeitem->child(i);
                queryTreeItemToStruct(psubtreeitem,nlrstruct);
            }
        }
    }
}

/*
 * 遍历结构体到树条目
 * ptreeitem : 树条目
 * nlrstruct : 结构体
 */
void TFrmStruct::queryStructToTreeItem(QTreeWidgetItem *ptreeitem,const TLRStruct &nlrstruct)
{    if(ptreeitem) {
        if(ptreeitem->childCount() == 0) {
            QString nvalstr = nlrstruct.getPara(ptreeitem->text(2),ptreeitem->text(3));
            ptreeitem->setText(1,nvalstr);
        }
        else {
            for(int i=0;i<ptreeitem->childCount();i++) {
                QTreeWidgetItem *psubtreeitem = ptreeitem->child(i);
                queryStructToTreeItem(psubtreeitem,nlrstruct);
            }
        }
    }

}

/*
 * 结构体数据更新
 */
void TFrmStruct::slotStructDataUpdate()
{
    TLRStruct nlrstruct = TLR::get()->m_lrStructModel.getStruct(m_index);
    for(int itopitem=0;itopitem<m_treeStructMonitor->topLevelItemCount();itopitem++) {
        QTreeWidgetItem *ptopitem = m_treeStructMonitor->topLevelItem(itopitem);
        //特殊处理字符串
        QString ntypestr = ptopitem->text(3);
        if(ntypestr.startsWith("char[") && (ptopitem->childCount() > 0)) {
            QString nvalstr = nlrstruct.getPara(ptopitem->text(2),ptopitem->text(3),ptopitem->childCount());
            ptopitem->setText(1,nvalstr);
        }
        if(ptopitem) {
            queryStructToTreeItem(ptopitem,nlrstruct);
        }
    }
}

/*
 * 分析树条目发生变化
 */
void TFrmStruct::slotTreeWidgetItemChanged(QTreeWidgetItem *item, int column)
{
    Q_UNUSED(column)
    //处理字符串
    if(item->childCount() > 0) {
        QByteArray nstringtoedit = item->text(1).toUtf8();
        for(int i=0;i<item->childCount();i++) {
            QTreeWidgetItem *psubitem = item->child(i);
            if(psubitem) {
                if(psubitem->text(3) == "char") {
                    if(i<nstringtoedit.size()) {
                        psubitem->setText(1,QString("'%1'").arg(nstringtoedit.at(i)));
                    }
                    else {
                        psubitem->setText(1,QString("%1").arg(0x00));
                    }
                }
            }
        }
    }
}
